{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "DweYe9FcbMK_"
      },
      "source": [
        "##### Copyright 2018 The TensorFlow Authors.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "colab": {},
        "colab_type": "code",
        "id": "AVV2e0XKbJeX"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "sUtoed20cRJJ"
      },
      "source": [
        "# Tải dữ liệu văn bản"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "1ap_W4aQcgNT"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/load_data/text\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />Xem trên TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/vi/tutorials/load_data/text.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Chạy trên Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/vi/tutorials/load_data/text.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />Xem mã nguồn trên GitHub</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/vi/tutorials/load_data/text.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Tải notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Cộng đồng TensorFlow tại Việt Nam đã và đang dịch những tài liệu này từ nguyên bản tiếng Anh. Những bản dịch này được hoàn thiện dựa trên sự nỗ lực đóng góp từ cộng đồng lập trình viên sử dụng TensorFlow, và điều này có thể không đảm bảo được tính cập nhật của bản dịch đối với [Tài liệu chính thức bằng tiếng Anh](https://www.tensorflow.org/?hl=en) này. Nếu bạn có bất kỳ đề xuất nào nhằm cải thiện bản dịch này, vui lòng tạo Pull request đến kho chứa trên GitHub của [tensorflow/docs-l10n](https://github.com/tensorflow/docs-l10n). Để đăng ký dịch hoặc cải thiện nội dung bản dịch, các bạn hãy liên hệ và đặt vấn đề tại [docs-vi@tensorflow.org](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-vi)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "NWeQAo0Ec_BL"
      },
      "source": [
        "Trong bài viết này chúng ta sẽ cùng tìm hiểu về cách sử dụng `tf.data.TextLineDataset` để tạo các mẫu dữ liệu từ tệp văn bản sẵn có. `TextLineDataset` được dùng để thiết kế một tập dữ liệu từ các tệp văn bản khác nhau, trong đó mỗi dòng trong văn bản gốc sẽ ứng với một mẫu trong tập dữ liệu (phù hợp với các văn bản được tổ chức theo dòng như thơ hoặc log lỗi).\n",
        "\n",
        "Ta sẽ sử dụng ba bản dịch tiếng Anh của tác phẩm Illiad được sáng tác bởi Homer để xây dựng mô hình cho phép xuất ra bản dịch tương ứng của từng dòng trong văn bản."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "fgZ9gjmPfSnK"
      },
      "source": [
        "## Chuẩn bị\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "baYFZMW_bJHh"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "\n",
        "import tensorflow_datasets as tfds\n",
        "import os"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "YWVWjyIkffau"
      },
      "source": [
        "Ta sẽ sử dụng bản dịch của các dịch giả sau:\n",
        "\n",
        " - [William Cowper](https://en.wikipedia.org/wiki/William_Cowper) — [bản dịch](https://storage.googleapis.com/download.tensorflow.org/data/illiad/cowper.txt)\n",
        "\n",
        " - [Edward, Earl of Derby](https://en.wikipedia.org/wiki/Edward_Smith-Stanley,_14th_Earl_of_Derby) — [bản dịch](https://storage.googleapis.com/download.tensorflow.org/data/illiad/derby.txt)\n",
        "\n",
        "- [Samuel Butler](https://en.wikipedia.org/wiki/Samuel_Butler_%28novelist%29) — [bản dịch](https://storage.googleapis.com/download.tensorflow.org/data/illiad/butler.txt)\n",
        "\n",
        "Các văn bản được sử dụng đều đã được tiền xử lý dữ liệu cơ bản (xóa header/footer của tài liệu, số dòng và tiêu đề chương). Chúng ta sẽ phải tải xuống các tệp này."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "4YlKQthEYlFw"
      },
      "outputs": [],
      "source": [
        "DIRECTORY_URL = 'https://storage.googleapis.com/download.tensorflow.org/data/illiad/'\n",
        "FILE_NAMES = ['cowper.txt', 'derby.txt', 'butler.txt']\n",
        "\n",
        "for name in FILE_NAMES:\n",
        "  text_dir = tf.keras.utils.get_file(name, origin=DIRECTORY_URL+name)\n",
        "  \n",
        "parent_dir = os.path.dirname(text_dir)\n",
        "\n",
        "parent_dir"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "q3sDy6nuXoNp"
      },
      "source": [
        "## Xây dựng tập dữ liệu từ văn bản\n",
        "\n",
        "Đầu tiên ta sẽ tạo ra các tập dữ liệu tương ứng với từng tệp văn bản.\n",
        "\n",
        "Về sau các tập dữ liệu này sẽ được gộp thành một tập lớn, do đó ta cần ghi chú lại tập dữ liệu gốc ứng với từng mẫu. Để làm được điều này, ta sẽ sử dụng `tf.data.Dataset.map` kết hợp với một hàm đánh nhãn. Khi truyền vào một mẫu, hàm sẽ trả về cặp dữ liệu `(example, label)` tương ứng."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "K0BjCOpOh7Ch"
      },
      "outputs": [],
      "source": [
        "def labeler(example, index):\n",
        "  return example, tf.cast(index, tf.int64)  \n",
        "\n",
        "labeled_data_sets = []\n",
        "\n",
        "for i, file_name in enumerate(FILE_NAMES):\n",
        "  lines_dataset = tf.data.TextLineDataset(os.path.join(parent_dir, file_name))\n",
        "  labeled_dataset = lines_dataset.map(lambda ex: labeler(ex, i))\n",
        "  labeled_data_sets.append(labeled_dataset)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "M8PHK5J_cXE5"
      },
      "source": [
        "Gộp các tập đã dán nhãn thành một tập dữ liệu lớn."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "6jAeYkTIi9-2"
      },
      "outputs": [],
      "source": [
        "BUFFER_SIZE = 50000\n",
        "BATCH_SIZE = 64\n",
        "TAKE_SIZE = 5000"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "Qd544E-Sh63L"
      },
      "outputs": [],
      "source": [
        "all_labeled_data = labeled_data_sets[0]\n",
        "for labeled_dataset in labeled_data_sets[1:]:\n",
        "  all_labeled_data = all_labeled_data.concatenate(labeled_dataset)\n",
        "  \n",
        "all_labeled_data = all_labeled_data.shuffle(\n",
        "    BUFFER_SIZE, reshuffle_each_iteration=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "r4JEHrJXeG5k"
      },
      "source": [
        "Để xem cặp `(example, label)` trả về, ta có thể sử dụng các hàm `tf.data.Dataset.take` and `print`. Giá trị trong thuộc tính `numpy` chính là giá trị của Tensor."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "gywKlN0xh6u5"
      },
      "outputs": [],
      "source": [
        "for ex in all_labeled_data.take(5):\n",
        "  print(ex)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "5rrpU2_sfDh0"
      },
      "source": [
        "## Encode mỗi dòng văn bản\n",
        "\n",
        "Các mô hình học máy nhận đầu vào là số. Do đó để xây dựng mô hình cho dữ liệu văn bản, các chuỗi văn bản cần được chuyển thành chuỗi các số. Nói cách khác, ta cần ánh xạ mỗi từ phân biệt thành một số phân biệt. \n",
        "\n",
        "### Xây dựng danh sách từ vựng\n",
        "\n",
        "Để xây dựng danh sách từ vựng, ta cần tách các chuỗi văn bản thành tập hợp các từ. Có nhiều cách để tách từ trong TensorFlow và Python. Tuy nhiên trong bài viết này, ta sẽ thực hiện như sau:\n",
        "\n",
        "1. Xét chuỗi văn bản trong thuộc tính `numpy` của từng mẫu.\n",
        "2. Sử dụng `tfds.features.text.Tokenizer` để tách chuỗi thành các token.\n",
        "3. Đưa token thu được vào cấu trúc set trong Python để loại bỏ các token trùng lặp.\n",
        "4. Lưu số lượng từ trong danh sách từ vựng để sử dụng về sau."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "YkHtbGnDh6mg"
      },
      "outputs": [],
      "source": [
        "tokenizer = tfds.features.text.Tokenizer()\n",
        "\n",
        "vocabulary_set = set()\n",
        "for text_tensor, _ in all_labeled_data:\n",
        "  some_tokens = tokenizer.tokenize(text_tensor.numpy())\n",
        "  vocabulary_set.update(some_tokens)\n",
        "\n",
        "vocab_size = len(vocabulary_set)\n",
        "vocab_size"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "0W35VJqAh9zs"
      },
      "source": [
        "### Encode các mẫu dữ liệu\n",
        "\n",
        "Ta sẽ tạo encoder bằng cách truyền `vocabulary_set` vào `tfds.features.text.TokenTextEncoder`. Phương thức `encode` của encoder nhận đầu vào là một chuỗi văn bản và trả về là chuỗi các số."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "gkxJIVAth6j0"
      },
      "outputs": [],
      "source": [
        "encoder = tfds.features.text.TokenTextEncoder(vocabulary_set)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "v6S5Qyabi-vo"
      },
      "source": [
        "Thử thực hiện encode trên một chuỗi văn bản mẫu để kiểm tra kết quả trả về."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "jgxPZaxUuTbk"
      },
      "outputs": [],
      "source": [
        "example_text = next(iter(all_labeled_data))[0].numpy()\n",
        "print(example_text)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "XoVpKR3qj5yb"
      },
      "outputs": [],
      "source": [
        "encoded_example = encoder.encode(example_text)\n",
        "print(encoded_example)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "p9qHM0v8k_Mg"
      },
      "source": [
        "Để sử dụng encoder với toàn bộ văn bản, ta cần \"đóng gói\" (wrap) nó vào trong một đối tượng là `tf.py_function` và truyền đối tượng này vào phương thức `map` của tập dữ liệu."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "HcIQ7LOTh6eT"
      },
      "outputs": [],
      "source": [
        "def encode(text_tensor, label):\n",
        "  encoded_text = encoder.encode(text_tensor.numpy())\n",
        "  return encoded_text, label"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "eES_Z1ia-Om-"
      },
      "source": [
        "Ta sẽ sử dụng `Dataset.map` để chạy hàm với từng mẫu trong tập dữ liệu. `Dataset.map` thực thi trên ở chế độ đồ thị:\n",
        "\n",
        "* Mỗi tensor trong đồ thị không chứa giá trị.\n",
        "* Ở chế độ đồ thị, ta chỉ có thể sử dụng toán tử (Ops) và hàm toán học (functions) trong TensorFlow.\n",
        "\n",
        "Do đó ta không thể truyền trực tiếp hàm đã viết vào `.map` mà phải thông qua `tf.py_function`. `tf.py_function` sẽ truyền tensor (bao gồm giá trị và phương thức `.numpy()` để truy cập giá trị đó) vào hàm đã viết.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "KmQVsAgJ-RM0"
      },
      "outputs": [],
      "source": [
        "def encode_map_fn(text, label):\n",
        "  # py_func doesn't set the shape of the returned tensors.\n",
        "  encoded_text, label = tf.py_function(encode, \n",
        "                                       inp=[text, label], \n",
        "                                       Tout=(tf.int64, tf.int64))\n",
        "\n",
        "  # `tf.data.Datasets` work best if all components have a shape set\n",
        "  #  so set the shapes manually: \n",
        "  encoded_text.set_shape([None])\n",
        "  label.set_shape([])\n",
        "\n",
        "  return encoded_text, label\n",
        "\n",
        "\n",
        "all_encoded_data = all_labeled_data.map(encode_map_fn)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "_YZToSXSm0qr"
      },
      "source": [
        "## Chia tập dữ liệu thành batch huấn luyện và batch kiểm thử\n",
        "\n",
        "Ta sẽ sử dụng `tf.data.Dataset.take` và `tf.data.Dataset.skip` để chia tập dữ liệu thành một tập nhỏ dành cho việc kiểm thử và tập lớn hơn còn lại cho việc huấn luyện.\n",
        "\n",
        "Trước khi đưa vào mô hình, tập dữ liệu cần được tổ chức thành từng batch. Thông thường các mẫu dữ liệu thuộc cùng một batch sẽ có cùng kích thước với nhau. Tuy nhiên trong dữ liệu hiện có, mỗi mẫu có kích thước khác nhau do mỗi dòng trong văn bản gốc có số lượng từ khác nhau. Vì thế ta sẽ sử dụng `tf.data.Dataset.padded_batch` (thay vì `batch`) để tất cả các mẫu có cùng kích thước bằng cách đệm thêm cho chúng."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "r-rmbijQh6bf"
      },
      "outputs": [],
      "source": [
        "train_data = all_encoded_data.skip(TAKE_SIZE).shuffle(BUFFER_SIZE)\n",
        "train_data = train_data.padded_batch(BATCH_SIZE)\n",
        "\n",
        "test_data = all_encoded_data.take(TAKE_SIZE)\n",
        "test_data = test_data.padded_batch(BATCH_SIZE)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Xdz7SVwmqi1l"
      },
      "source": [
        "Kể từ bây giờ, dữ liệu trong `test_data` và `train_data` không tổ chức theo dạng tập hợp các cặp `(example, label)` mà là tập hợp các batch. Mỗi batch là một cặp *(nhiều mẫu, nhiều nhãn)* được biễu diễn dưới dạng mảng.\n",
        "\n",
        "Ví dụ:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "kMslWfuwoqpB"
      },
      "outputs": [],
      "source": [
        "sample_text, sample_labels = next(iter(test_data))\n",
        "\n",
        "sample_text[0], sample_labels[0]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "UI4I6_Sa0vWu"
      },
      "source": [
        "Số lượng từ trong danh sách từ vựng lúc này cần tăng lên 1 vì ta vừa bổ sung một token mới là số 0 được sử dụng trong quá trình đệm dữ liệu."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "IlD1Lli91vuc"
      },
      "outputs": [],
      "source": [
        "vocab_size += 1"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "K8SUhGFNsmRi"
      },
      "source": [
        "## Xây dựng mô hình"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "QJgI1pow2YR9"
      },
      "outputs": [],
      "source": [
        "model = tf.keras.Sequential()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "wi0iiKLTKdoF"
      },
      "source": [
        "Tầng đầu tiên của mô hình sẽ chuyển các chuỗi văn bản được biểu diễn dưới dạng số thành các vector embedding dày đặc. Xem thêm tại [Hướng dẫn về word embeddings](../text/word_embeddings.ipynb)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "DR6-ctbY638P"
      },
      "outputs": [],
      "source": [
        "model.add(tf.keras.layers.Embedding(vocab_size, 64))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "_8OJOPohKh1q"
      },
      "source": [
        "Tiếp theo sẽ là tầng [Bộ nhớ Ngắn hạn Dài - *Long Short-Term Memory (LSTM)*](http://colah.github.io/posts/2015-08-Understanding-LSTMs/) cho phép mô hình xác định ý nghĩa của một từ trong ngữ cảnh của nó. Bidirectional được bổ sung bên ngoài tầng LSTM giúp mô hình học được mối quan hệ giữa điểm dữ liệu được xét và các điểm trước và sau nó."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "x6rnq6DN_WUs"
      },
      "outputs": [],
      "source": [
        "model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64)))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "cdffbMr5LF1g"
      },
      "source": [
        "Cuối cùng ta sẽ cần một hoặc nhiều tầng kết nối dày đặc (*densely connected layer*), trong đó tầng cuối cùng sẽ đóng vai trò là tầng đầu ra. Tầng đầu ra sẽ trả về xác suất ứng với từng nhãn. Nhãn có xác suất cao nhất chính là giá trị tiên đoán của mô hình. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "QTEaNSnLCsv5"
      },
      "outputs": [],
      "source": [
        "# One or more dense layers.\n",
        "# Edit the list in the `for` line to experiment with layer sizes.\n",
        "for units in [64, 64]:\n",
        "  model.add(tf.keras.layers.Dense(units, activation='relu'))\n",
        "\n",
        "# Output layer. The first argument is the number of labels.\n",
        "model.add(tf.keras.layers.Dense(3))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "zLHPU8q5DLi_"
      },
      "source": [
        "Ta sẽ biên dịch mô hình với hàm mất mát là `sparse_categorical_crossentropy` (dành cho mô hình phân loại) và trình tối ưu hóa là `adam` (có nhiều lựa chọn, tuy nhiên `adam` là lựa chọn phổ biến nhất)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "pkTBUVO4h6Y5"
      },
      "outputs": [],
      "source": [
        "model.compile(optimizer='adam',\n",
        "              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),\n",
        "              metrics=['accuracy'])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "DM-HLo5NDhql"
      },
      "source": [
        "## Huấn luyện mô hình\n",
        "\n",
        "Mô hình đã xây dựng chạy trên tập dữ liệu cho kết quả tương đối khả quan (khoảng 83%)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "aLtO33tNh6V8"
      },
      "outputs": [],
      "source": [
        "model.fit(train_data, epochs=3, validation_data=test_data)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {},
        "colab_type": "code",
        "id": "KTPCYf_Jh6TH"
      },
      "outputs": [],
      "source": [
        "eval_loss, eval_acc = model.evaluate(test_data)\n",
        "\n",
        "print('\\nEval loss: {:.3f}, Eval accuracy: {:.3f}'.format(eval_loss, eval_acc))"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "text.ipynb",
      "private_outputs": true,
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
